<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      //   1.obj ?.prop. --------如果obj 存在则返回 obj.prop ,否则返回 undefined。
      //   2.obj ?.[prop] -------如果存在则返回obj[prop] ，否则返回undefined。
      //   3.obj.method?.()------如果obj.method 存在则调用obj.method(),否则返回undefined。
      //   正如我们所看到的，这些语法形式用起来都很简单直接，检查左边部分是否为 null/undefined，如果不是则继续运算。
      //   二、可选链
      //   	**1.为什么需要可选链？**
      //   	当我们之前访问一个不存在的属性，会报错error
      //   let user = {}; // 一个没有 "address" 属性的 user 对象
      // 	alert(user.address.street); // Error!

      //   let user = {}; // user 没有 address 属性
      //   alert(user?.address?.street); // undefined（不报错）
      //   正如前面所说，如果 ?. 前面的 部分不存在，就会立即停止运算（“短路效应”），
      // 这个时候，如果后面有任何函数或者副作用，他们均不会执行

      let user = null;
      let x = 0;

      user?.sayHi(x++); // 没有 "sayHi"，因此代码执行没有触达 x++

      alert(x); // 0，值没有增加

      // 例如:将 ?.() 用于调用 一个可能不存在的函数
      let userAdmin = {
        admin() {
          alert("I am admin");
        },
      };

      let userGuest = {};

      userAdmin.admin?.(); // I am admin

      userGuest.admin?.(); // 啥都没有（没有这样的方法）

      // ?.[] 用来访问属性，和之前例子相似
      let user1 = {
        firstName: "John",
      };

      let user2 = null; // 假设，我们不能授权此用户

      let key = "firstName";

      alert(user1?.[key]); // John
      alert(user2?.[key]); // undefined

      alert(user1?.[key]?.something?.not?.existing); // undefined
    </script>
  </body>
</html>
